package com.khalil.kkadmin.cms.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.khalil.kkadmin.cms.domain.CmsColumn;
import com.khalil.kkadmin.cms.repository.CmsColumnRepository;
import com.khalil.kkadmin.cms.service.CmsColumnService;
import com.khalil.kkadmin.common.util.TreeUtil;
import com.khalil.kkadmin.infrastructure.BaseService;
import org.springframework.stereotype.Service;

import java.util.Comparator;
import java.util.List;

@Service
public class CmsColumnServiceImpl extends BaseService<CmsColumnRepository, CmsColumn, Long> implements CmsColumnService {
    public CmsColumnServiceImpl(CmsColumnRepository repository) {
        super(repository);
    }

    public static final String DRAG_TYPE_BEFORE = "before";
    public static final String DRAG_TYPE_AFTER = "after";
    public static final String DRAG_TYPE_INNER = "inner";
    public static final String TREE_PATH_SPLIT = ",";

    @Override
    protected CmsColumn str2CreateEntity(String json) {
        return JSONObject.parseObject(json, CmsColumn.class);
    }

    @Override
    protected CmsColumn str2UpdateEntity(String json) {
        return JSONObject.parseObject(json, CmsColumn.class);
    }

    @Override
    public List<CmsColumn> list(String params) {
        return List.of();
    }

    @Override
    public List<CmsColumn> listTree() {
        List<CmsColumn> dirList = findAll();
        TreeUtil.sortTree(dirList, Comparator.comparing(CmsColumn::getOrderNum));
        return TreeUtil.buildTree(dirList, (menu) -> menu.getParentId() == null || menu.getParentId() <= 0);
    }

    @Override
    public void dragMove(Long id, Long refId, String dropType) {
        CmsColumn column = repository.findById(id).orElseThrow(RuntimeException::new);
        CmsColumn refColumn = repository.findById(refId).orElseThrow(RuntimeException::new);
        if (DRAG_TYPE_BEFORE.equals(dropType)) {
            Long parentId = refColumn.getParentId();
            column.setParentId(parentId);
            String treePath = computeTreePathFromBrother(id, refColumn);
            column.setTreePath(treePath);
            column.setOrderNum(refColumn.getOrderNum());
            refColumn.setOrderNum(refColumn.getOrderNum() + 1);
            repository.save(column);
            repository.save(refColumn);
            // 更新排序
            Integer refOrderNum = refColumn.getOrderNum();
            multiUpdateChildrenOrderNum(id, parentId, refOrderNum);
        } else if (DRAG_TYPE_AFTER.equals(dropType)) {
            Long parentId = refColumn.getParentId();
            column.setParentId(parentId);
            String treePath = computeTreePathFromBrother(id, refColumn);
            column.setTreePath(treePath);
            column.setOrderNum(refColumn.getOrderNum() + 1);
            repository.save(column);
            // 更新排序
            Integer refOrderNum = refColumn.getOrderNum();
            multiUpdateChildrenOrderNum(id, parentId, refOrderNum);
        } else if (DRAG_TYPE_INNER.equals(dropType)) {
            Long parentId = refColumn.getId();
            column.setParentId(parentId);
            column.setTreePath(refColumn.getTreePath() + TREE_PATH_SPLIT + id);
            Integer maxOrderNum = repository.findMaxOrderNumByParentId(parentId);
            column.setOrderNum(maxOrderNum == null ? 0 : maxOrderNum + 1);
            repository.save(column);
        } else {
            throw new RuntimeException("dropType参数错误");
        }
    }

    private void multiUpdateChildrenOrderNum(Long startId, Long parentId, Integer refOrderNum) {
        List<CmsColumn> dirList = repository.findByParentIdOrderByOrderNum(parentId);
        int orderNum = refOrderNum;
        boolean flag = false;
        for (CmsColumn column : dirList) {
            if (column.getId().equals(startId)) {
                flag = true;
            } else {
                if (flag) {
                    orderNum++;
                    repository.updateOrderNum(column.getId(), orderNum);
                }
            }
        }
    }

    private String computeTreePathFromBrother(Long id, CmsColumn refColumn) {
        String treePath = refColumn.getTreePath();
        if (treePath.endsWith(TREE_PATH_SPLIT)) {
            treePath = treePath.substring(0, treePath.length() - 1);
        }
        String parentTreePath = treePath.substring(0, treePath.lastIndexOf(TREE_PATH_SPLIT) + 1);
        treePath = parentTreePath + id;
        return treePath;
    }
}
